package org.tloss.proxyserver.filter;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.tloss.proxyserver.Constants;
import org.tloss.proxyserver.ProxyContextEntry;
import org.tloss.proxyserver.ProxyEntry;
import org.tloss.proxyserver.ProxyMangager;

public class ProxyServerFilter implements Filter {

	private AdminFilterHandler adminFilterHandler = new AdminFilterHandler();
	private ResourceFilterHandler resourceFilterHandler = new ResourceFilterHandler();

	public void destroy() {
		adminFilterHandler.destroy();
		adminFilterHandler = null;
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		StringBuffer resource = new StringBuffer();
		HttpServletRequest servletRequest = (HttpServletRequest) request;
		String servletPath = servletRequest.getServletPath();
		String pathInfo = servletRequest.getPathInfo();
		if (servletPath != null) {
			resource.append(servletPath);
		}
		if (pathInfo != null) {
			resource.append(pathInfo);
		}
		String URI = resource.toString();
		if (URI.startsWith(Constants.PROXY_ADMIN_PATH)) {
			adminFilterHandler.doFilter(URI, servletRequest,
					(HttpServletResponse) response, chain);
		} else {
			ProxyMangager mangager = ProxyMangager.getInstanse();
			Map<String, ProxyContextEntry> contextEntries = mangager
					.getContextEntries();
			Set<Entry<String, ProxyContextEntry>> entries = contextEntries
					.entrySet();
			ProxyContextEntry contextEntry;
			boolean found = false;
			String context;
			for (Iterator<Entry<String, ProxyContextEntry>> i = entries
					.iterator(); !found && i.hasNext();) {
				contextEntry = i.next().getValue();
				context = contextEntry.getContext();
				if (URI.startsWith(context)) {
					found = true;
					if (URI.startsWith(context + Constants.PROXY_RESOURCES_PATH)) {
						resourceFilterHandler.doFilter(URI, servletRequest,
								(HttpServletResponse) response, chain);
					} else {
						// handle it
						StringBuffer location = new StringBuffer();
						List<String> hash = contextEntry.getHashList();
						ProxyEntry proxyEntry = contextEntry.getProxyEntries()
								.get(hash.get(0));
						location.append(proxyEntry.getProtocol()).append("://")
								.append(proxyEntry.getHost()).append(":")
								.append(proxyEntry.getPort())
								.append(proxyEntry.getContext()).append(URI);
						((HttpServletResponse) response).sendRedirect(location
								.toString());
					}
				}
			}
			if (!found)
				chain.doFilter(request, response);
		}
	}

	public void init(FilterConfig config) throws ServletException {
		ProxyMangager mangager = ProxyMangager.getInstanse();
		mangager.init();
		adminFilterHandler.init();
	}

}
